import base64
import hmac
import urllib

from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

#from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from myapp.models import User
from myapp.myser import UserSer
from mydjango.settings import UPLOAD_ROOT
from mydjango.settings import qiniu_AK,qiniu_SK
from mydjango.settings import Base_URL_vue
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

#定义host和端口
host = '127.0.0.1'
port = 6379
r = redis.Redis(host=host,port=port)




from django.utils.deprecation import MiddlewareMixin
#自定义中间件与JWT联合实现验证
class MyMiddleWare(MiddlewareMixin):
    #请求之前
    def process_request(self,request):
        #获取客户端传来的uid、jwt-token
        # uid = request.GET.get("uid")
        # client_jwt = request.GET.get("jwt",'null')
        #
        # #进行解密，然后比对
        # try:
        #     decode_jwt = jwt.decode(client_jwt, '0722', algorithms=['HS256'])
        #     if str(decode_jwt['uid']) != str(uid):
        #         return HttpResponse("你篡改了用户ID！！")
        # except Exception as e:
        #     return HttpResponse("你篡改了用户ID！！")
        pass


    #模板渲染之前
    def process_view(self,request,view_func,view_args,view_kwargs):
        pass

    #请求之后
    def process_response(self,request,response):
        return response

#装饰器的使用
def my_decorator(func):
    def warpper(request,*args,**kwargs):
        # print('测试，被调用')
        # print('请求接口地址是{}'.format(request.path))
        #判断JWT逻辑
        uid = request.GET.get("uid")
        client_jwt = request.GET.get("jwt",'null')

        #进行解密，然后比对
        try:
            decode_jwt = jwt.decode(client_jwt, '0722', algorithms=['HS256'])
            if str(decode_jwt['uid']) != str(uid):
                return HttpResponse("你篡改了用户ID！！")
        except Exception as e:
            return HttpResponse("你篡改了用户ID！！")
        return func(request,*args,**kwargs)
    return warpper

#类装饰器调用
from django.utils.decorators import method_decorator
#用户信息类
class UserInfo(APIView):
    @method_decorator(my_decorator)
    def get(self,request):
        uid = request.GET.get("uid")
        #查询数据
        user = User.objects.get(id = int(uid))
        #序列化对象
        user_ser = UserSer(user)
        return Response(user_ser.data)

#更新用户头像/数据
class UpdateUserImg(APIView):
    def get(self,request):
        #获取数据
        img = request.GET.get('img')
        username = request.GET.get("username")

        user = User.objects.filter(username=username).first()
        if user:
            #修改头图
            user.img = img
            user.save()
            result={}
            result['code']=200
            result['message'] = '修改用户头像成功'
            return Response(result)
        else:
            result={}
            result["code"] = 405
            result['message'] = '未知错误'
            return Response(result)

#定义七牛云存储接口
from qiniu import Auth
class Qiniu(APIView):
    def get(self,request):
        #定义密钥
        q = Auth(qiniu_AK,qiniu_SK)
        #指定上传空间mdmd2020
        token = q.upload_token('mdmd2020')
        print(token)
        res = {}
        res['token'] = token
        #只给前端返回一个token
        return Response(res)

#修改密码
class UserModify(APIView):
    def get(self,request):
        username = request.GET.get("username",'null')
        password = request.GET.get("password",'null')

        user = User.objects.filter(username=username).first()
        if user.password == make_password(password):
            resp = {}
            resp["code"] = 405
            resp["message"] = '密码与先前密码一致！！'
            return Response(resp)
        else:
            user.password = make_password(password)
            user.save()
            resp = {}
            resp["code"] = 200
            resp["message"] = '修改密码成功！'
            return Response(resp)

#定义上传视图类
class Upload_File(View):
    def post(self,request):
        #接受参数
        img = request.FILES.get('file')
        #建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT,'',img.name.replace('"',"")),'wb')
        #写入
        for chunk in img.chunks():
            f.write(chunk)
        #关闭文件
        f.close()

        #添加水印
        # 思路：用画笔打开 图片，再将水印画到图片上
        #很奇怪为什么相对路径打不开
        image = Image.open('D:\\workspace\\www\\mydjango_1906\\static\\upload\\'+img.name)
        # print(image.size)
        # 生成画笔对象
        draw = ImageDraw.Draw(image)
        # 定义字体
        myfont = ImageFont.truetype(font='C:\\Windows\\Fonts\\STCAIYUN.TTF')
        # 修改
        draw.text((150, 150), '1906', fill=(176, 34, 224, 180), font=myfont)
        # 查看图片
        # 存储图片,直接覆盖了
        image.save('D:\\workspace\\www\\mydjango_1906\\static\\upload\\'+img.name)
        # 查看图片
        # image.show()

        #返回文件名
        return HttpResponse(json.dumps({'filename':img.name},ensure_ascii=False),content_type='application/json')


#钉钉登录回调
def ding_back(request):
    #获取授权码code&返回的state
    code = request.GET.get("code",'null')
    state = request.GET.get("state",'null')


    #钉钉开放平台提供的
    appId = 'dingoajtt4hfxbsp1tpdyv'
    appSecret = 'R7krrBZnXzoRGrHaJR9dhaYb_qgTOtq86dpreWThg60tiHfoenzCyZ6zNOmxb-9Y'
    #构建时间戳(单位毫秒)
    now_milli_time = str(int(time.time() * 1000))
    #构建签名
    signature = base64.b64encode(
        hmac.new(
            appSecret.encode('utf-8'),
            now_milli_time.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()).decode("utf-8")
    #通过临时授权码获取用户个人信息
    #post参数需要json类型
    #url签名参数写进url，data参数使用json
    res = requests.post(url='https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey='
                            +appId+'&timestamp='+now_milli_time+'&signature='+urllib.parse.quote(signature),
        data=json.dumps({
            "tmp_auth_code": code
        }),
        headers={
            'Content-Type': 'application/json'
        }
    )

    #转码，获取用户名
    res = json.loads(res.text)
    name = res['user_info']['nick']

    # 判断是否使用过钉钉登录
    user = User.objects.filter(username=name).first()
    ding_id = ''
    user_id = ''
    if user:
        # 表示已经使用过微博登录并且成功注册到了数据库
        ding_id = user.username
        user_id = user.id
    else:
        # 首次登录，需要存储到数据库
        user = User(username=name, password='', type=0)
        user.save()

        # 查询用户ID
        user = User.objects.filter(username=name).first()
        ding_id = ding_id
        user_id = user.id

    return redirect(Base_URL_vue+'?ding_id='+str(ding_id)+'&user_id='+str(user_id))

#新浪微博回调
def wb_back(request):
    #获取code
    code = request.GET.get("code")
    #定义微博认证地址
    accept_token_url = 'https://api.weibo.com/oauth2/access_token'
    #参数
    res = requests.post(
        url=accept_token_url,
        data={'client_id':'2852114568',
              'client_secret':'fc391b9cf804f40d1309fd2f1e014abd',
              'grant_type':'authorization_code',
              'code':code,
              'redirect_uri':'http://127.0.0.1:8000/md_admin/weibo'
              }
    )

    #转换类型
    res = json.loads(res.text)
    wbuid = res['uid']
    # print(type(wbuid),wbuid)

    # 获取新浪微博昵称
    result = requests.get(url='https://api.weibo.com/2/users/show.json',params={
        'access_token':res['access_token'],
        'uid':wbuid,
    })

    result = json.loads(result.text)

    # 判断是否使用过sina微博登录
    user = User.objects.filter(username=result['name']).first()
    sina_id = ''
    user_id = ''
    if user:
        #表示已经使用过微博登录并且成功注册到了数据库
        sina_id = user.username
        user_id = user.id
    else:
        #首次登录，需要存储到数据库
        user = User(username=result['name'],password='')
        user.save()

        #查询用户ID
        user = User.objects.filter(username=result['name']).first()
        sina_id = user.username
        user_id = user.id

    return redirect('http://127.0.0.1:8080/?sina_id='+str(sina_id)+"&uid="+str(user_id))
    # return HttpResponse(result['name'])

#登录模块
class Login(APIView):
    def get(self,request):
        #接受参数
        username = request.GET.get("username",'null')
        password = request.GET.get("password",'null')

        #查询数据库
        user = User.objects.filter(username=username,password=make_password(password)).first()
        if user:
            res = {}
            res['code']=200
            res["message"]='登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            #加入jwt令牌机制
            # 进行编码
            encode_jwt = jwt.encode({'uid': str(user.id)}, '0722', algorithm='HS256')
            encode_str = str(encode_jwt, 'utf-8')
            res['jwt'] = encode_str
            return Response(res)
        else:
            res = {}
            res['code'] = 450
            res["message"] = '用户名或密码错误'
            return Response(res)

#验证码操作
class MyCode(View):
    def get_random_color(self):
        #工具方法，定义颜色
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R,G,B)

    #获取验证码视图
    def get(self,request):
        #画布
        img_size = (150,50)
        #定义画图对象
        image = Image.new('RGB',img_size,'white')
        #定义画笔对象
        draw = ImageDraw.Draw(image,'RGB')
        #定义随机字符串
        source = '0123456789qwertyuiop'
        #定义容器，接受字符串
        code_str = ''
        #定义字体
        my_font = ImageFont.truetype(font='C:\\Windows\\Fonts\\ARLRDBD.TTF',size=30)
        for i in range(4):
            #获取随机颜色
            test_color = self.get_random_color()
            #获取随机字符串长度
            tep_num = random.randrange(len(source))
            #获取字符集
            random_str = source[tep_num]
            #添加到容器中
            code_str += random_str
            #将字符串添加到画布
            draw.text((10+30*i,10),random_str,test_color,font=my_font)
        #建立缓存区,在内存中开辟空间
        buf = io.BytesIO()
        #将验证码存储到redis中
        r.set("code",code_str)

        #保存图片
        image.save(buf,'png')
        return HttpResponse(buf.getvalue(),'image/png')


#注册模块
class Register(APIView):
    def get(self,request):
        username = request.GET.get("username","null")
        password = request.GET.get("password",'null')
        code = request.GET.get("code",'null')

        #查看接收参数
        print(username)
        print(password)
        redis_code = r.get("code").decode("utf8")
        # 查、看
        print(redis_code)
        print(code)

        if code != redis_code:
            res = {}
            res["code"] = 405
            res["message"] = '验证码输入错误！！'
            return Response(res)

        #排重(需要优先判断验证码）
        user = User.objects.filter(username=username).first()

        if user:
            res = {}
            res["code"] = 405
            res["message"] = '该用户名已存在！'
            return Response(res)
        else:
            user = User(username=username,password=make_password(password))
            user.save()
            res = {}
            res["code"] = 200
            res["message"] = '恭喜注册成功！'
            return Response(res)

#md5加密逻辑
def make_password(mypass):

    #生成md5对象
    md5 = hashlib.md5()
    #定义机密对象——进行强转
    sign_str = str(mypass)
    #转码
    sign_utf8 = sign_str.encode(encoding="utf-8")
    #加密
    md5.update(sign_utf8)
    #生成密钥串
    md5_server = md5.hexdigest()

    return md5_server




#方法视图
def myindex(request):

    return HttpResponse('这里是首页')


#类视图
class MyView(View):

    greeting = '你好，这里是首页'

    def get(self,request):

        title = "你好啊，Django！"
        num = 123
        test_list =[1,2,23,4,5,6,7,8,9]
        dict = {"name":"汽车","price":100}


        # return HttpResponse(self.greeting)
        return render(request,'test.html',locals())
